#include "buff_detect.h"

buff_detect::buff_detect(int& color)
{
	dst.create(Size(GWIDTH, GHEIGHT), CV_8UC1);

	FileStorage fs2("./xml/test.xml", FileStorage::READ);

	fs2["color"] >> color;

	if (color == 0)
		fs2["thresh0"] >> threshValue;//蓝色
	else
		fs2["thresh1"] >> threshValue;//红色

	fs2["gray_dilate_size"] >> gray_dilate_size;
	fs2["gray_threshValue"] >> gray_threshValue;
	fs2["f_s_area_max"] >> f_s_area_max;
	fs2["f_s_area_min"] >> f_s_area_min;
	fs2["father_area_min"] >> father_area_min;
	fs2["father_area_max"] >> father_area_max;
	fs2["son_area_max"] >> son_area_max;
	fs2["son_area_min"] >> son_area_min;
	fs2["dilate_size"] >> dilate_size;
	fs2["erode_size"] >> erode_size;
	fs2["say_area"] >> say_area;

	fs2.release();

#ifdef DEBUG
	namedWindow("DEBUG");
	createTrackbar("s_area_min", "DEBUG", &son_area_min, 10000);
	createTrackbar("s_area_max", "DEBUG", &son_area_max, 10000);
	createTrackbar("f_area_min", "DEBUG", &father_area_min, 10000);
	createTrackbar("f_area_max", "DEBUG", &father_area_max, 10000);
	createTrackbar("gray", "DEBUG", &gray_threshValue, 255);
	createTrackbar("r_b", "DEBUG", &threshValue, 255);
	createTrackbar("color", "DEBUG", &color, 1);
#endif // DEBUG
}

int buff_detect::BuffDetectTask(Mat& image, float& angle, struct logo& center_r)//dst��ɫͨ�����   imageԭͼ��  angle_num�õ��ǶȵĴ���
{
	vector<RotatedRect> target_armor;//存储装甲板
	vector<RotatedRect> target_r;//存储识别到的R形logo
	vector<RotatedRect> final_r;//最终得到的R形logo

	buff_detection(image, target_r, target_armor);

	if (target_armor.empty())
	{
		cout << "1111111   " ;
		return 0;
	}

	if (target_r.empty())
	{
		cout << "2222222   " ;
		return 0;
	}


#ifdef MLR
	machineLearning(image, target_r, final_r, svm1);
#else 
	final_r.push_back(target_r[0]);
#endif // MLR

#ifdef DEBUG	
	box.drawBoxGreen(target_armor[0], image);
	box.drawBoxYellow(final_r[0], image);
#endif // DEBUG

	if (final_r.empty())
	{
		return 0;
	}
	
	center_r.r = sqrt(powf((target_armor[0].center.x - final_r[0].center.x), 2) + 
					powf((target_armor[0].center.y - final_r[0].center.y), 2));

	center_r.x = final_r[0].center.x;
	center_r.y = final_r[0].center.y;

	//扇叶相对于能量机关中心的旋转角度
	float delta_x = abs(target_armor[0].center.x - final_r[0].center.x);
	float delta_y = abs(target_armor[0].center.y - final_r[0].center.y);
	float theta = atan(delta_x / delta_y) / PI * 180;

	if (delta_x != 0 || delta_y != 0)
	{
		if (target_armor[0].center.x > final_r[0].center.x && target_armor[0].center.y < final_r[0].center.y)//��һ����
		{
			angle = theta;
		}
		else if (target_armor[0].center.x > final_r[0].center.x && target_armor[0].center.y > final_r[0].center.y)//�ڶ�����
		{
			angle = 180.0 - theta;
		}
		else if (target_armor[0].center.x < final_r[0].center.x && target_armor[0].center.y > final_r[0].center.y)//��������
		{
			angle = 180.0 + theta;
		}
		else if (target_armor[0].center.x < final_r[0].center.x && target_armor[0].center.y < final_r[0].center.y)//��������
		{
			angle = 360.0 - theta;
		}
	}
	else
	{
		if (delta_x == 0 && target_armor[0].center.y < final_r[0].center.y)//y�ϰ���
		{
			angle = 0.0;
		}
		else if (delta_x == 0 && target_armor[0].center.y > final_r[0].center.y)//y�°���
		{
			angle = 180.0;
		}
		else if (delta_y == 0 && target_armor[0].center.x < final_r[0].center.x)//x�����
		{
			angle = 270.0;
		}
		else if (delta_y == 0 && target_armor[0].center.x > final_r[0].center.x)//x�Ұ���
		{
			angle = 90.0;
		}
	}

	return target_armor.size();
}

void buff_detect::color_buff(Mat image, int color)
{
	for (int i = 0; i < image.rows; i++)
	{
		uchar* data_b = image.ptr<uchar>(i);
		uchar* data_r = image.ptr<uchar>(i) + 2;

		for (int j = 0; j < image.cols; j++)
		{
			if (color == 0)
			{
				dst.ptr<uchar>(i)[j] = saturate_cast<uchar>(*data_b - *data_r);
				if (dst.ptr<uchar>(i)[j] < threshValue )
				{
					dst.ptr<uchar>(i)[j] = 0;
				}
				else
				{
					dst.ptr<uchar>(i)[j] = 255;
				}
			}

			if (color == 1)
			{
				dst.ptr<uchar>(i)[j] = saturate_cast<uchar>(*data_r - *data_b);

				if (dst.ptr<uchar>(i)[j] < threshValue)
				{
					dst.ptr<uchar>(i)[j] = 0;
				}
				else
				{
					dst.ptr<uchar>(i)[j] = 255;
				}
			}

			data_b = data_b + 3;
			data_r = data_r + 3;
		}
	}

	Mat gray_elementDilate = getStructuringElement(MORPH_ELLIPSE, Size(gray_dilate_size, gray_dilate_size));
	Mat elementDilate = getStructuringElement(MORPH_ELLIPSE, Size(dilate_size, dilate_size));
	Mat elementErode = getStructuringElement(MORPH_ELLIPSE, Size(erode_size, erode_size));

	//对颜色通道相减二值图的预处理
	//闭运算消除黑洞
	dilate(dst, dst, elementDilate);
	erode(dst, dst, elementErode);

	Mat gray;
	//得到灰度图
	cvtColor(image, gray, COLOR_RGB2GRAY);
	gray_dst = dst & gray;
	
	threshold(gray_dst, gray_dst, gray_threshValue, 255, 0);

	//对灰度二值图的预处理
	//闭运算消除黑洞
	dilate(gray_dst, gray_dst, gray_elementDilate);
	erode(gray_dst, gray_dst, elementErode);
	erode(gray_dst, gray_dst, elementErode);
}

void buff_detect::buff_detection(Mat& image, vector<RotatedRect>& target_r, vector<RotatedRect>& target_armor)
{

#ifdef DEBUG
	imshow("r_b", dst);
	imshow("gray_dst", gray_dst);
#endif //DEBUG

	RotatedRect father;
	RotatedRect son;
	
	vector<vector<Point>> lightContours;
	vector<Vec4i> hierarchy;
	vector<RotatedRect> rect;

	//寻找扇叶以及装甲板的轮廓
	findContours(gray_dst, lightContours, hierarchy, RETR_TREE, CHAIN_APPROX_NONE);

	for (int i = 0; i < lightContours.size(); i++)
	{
		if (lightContours[i].size() > 6)
		{
			rect.push_back(fitEllipse(lightContours[i]));
		}
	}

	if (rect.size() == 0)
	{
		return;
	}

	for (int i = 0; i < rect.size(); i++)
	{
		RotatedRect light;

		light = rect[i];

		//边缘保护
		int light_x = 0, light_y = 0;
		light_x = abs(light.center.x);
		light_y = abs(light.center.y);
		if (light_x + light.size.width / 2 > image.cols || light_y + light.size.height / 2 > image.rows ||
			light_x - light.size.width / 2 < 0 || light_y - light.size.height / 2 < 0)
		{
			continue;
		}

		//有父轮廓
		if (hierarchy[i][3] != -1)
		{
			son_num = i;
			son = light;
			father = rect[hierarchy[i][3]];
			ok = true;
		}

		//扇叶没有父轮廓，有子轮廓
		if (ok)
		{
			ok = false;

			float vilue = 0;

			vilue = (father.size.width > father.size.height) ? father.size.width / father.size.height : father.size.height / father.size.width;
			
			if (vilue > 1 && vilue < 4)
			{
				if (father.size.area() < father_area_min || father.size.area() > father_area_max)
				{
					//cout << 4 << endl;
					continue;
				}

				//对子轮廓即目标装甲板 进行条件限制
				if (hierarchy[son_num][0] == -1 && hierarchy[son_num][1] == -1)//目标装甲板没有同级轮廓
				{					
					if (son.size.area() < son_area_min || son.size.area() > son_area_max)
					{
						continue;
					}
					
					if (father.size.area() / son.size.area() > f_s_area_min && father.size.area() / son.size.area() < f_s_area_max)
					{
						if (say_area == 1)
						{
							cout << "son.size.area()  = " << son.size.area();
							cout << "    father.size.area()  = " << father.size.area() << endl;
							//cout << "    f_s = " << father.size.area() / son.size.area() << endl;
						}

						target_armor.push_back(son);//得到目标

						get_r = true;
						break;
					}
				}
			}
		}		
	}

	if (get_r)
	{
		get_energy_center(image, father, son, rect, target_r);

		get_r = false;
	}
}

void buff_detect::get_energy_center(Mat image, RotatedRect father, RotatedRect son, vector<RotatedRect> rect, vector<RotatedRect>& target_r)
{
	float delta_x = son.center.x - father.center.x;//装甲板相对于扇叶x的偏移
	float delta_y = son.center.y - father.center.y;//装甲板相对于扇叶y的偏移
	float distance = father.size.width + father.size.height;//当扇叶在

	float father_center_to_son_center = sqrt(powf(delta_x, 2) + powf(delta_y, 2));//扇叶中心与装甲板中心的距离
	float Y = abs(delta_y * distance / father_center_to_son_center);//ROI中心相对于装甲板Y的偏移量
	float X = abs(delta_x * distance / father_center_to_son_center);//ROI中心相对于装甲板X的偏移量
	float ROI_center_x = 0;
	float ROI_center_y = 0;

	//根据装甲板相对于扇叶的位置，确定ROI区域的中心位置
	if (delta_x != 0 && delta_y != 0)
	{
		if (son.center.x < father.center.x && son.center.y < father.center.y)
		{
			ROI_center_x = son.center.x + father_center_to_son_center * 2;
			ROI_center_y = son.center.y + father_center_to_son_center * 2;
		}
		else if (son.center.x < father.center.x && son.center.y > father.center.y)
		{
			ROI_center_x = son.center.x + father_center_to_son_center * 2;
			ROI_center_y = son.center.y - father_center_to_son_center * 2;
		}
		else if (son.center.x > father.center.x && son.center.y > father.center.y)
		{
			ROI_center_x = son.center.x - father_center_to_son_center * 2;
			ROI_center_y = son.center.y - father_center_to_son_center * 2;
		}
		else if (son.center.x > father.center.x && son.center.y < father.center.y)
		{
			ROI_center_x = son.center.x - father_center_to_son_center * 2;
			ROI_center_y = son.center.y + father_center_to_son_center * 2;
		}
	}
	else
	{
		if (delta_x == 0 && delta_y > 0)
		{
			ROI_center_x = son.center.x;
			ROI_center_y = son.center.y + distance;
		}
		else if (delta_x == 0 && delta_y < 0)
		{
			ROI_center_x = son.center.x;
			ROI_center_y = son.center.y - distance;
		}
		else if (delta_x > 0 && delta_y == 0)
		{
			ROI_center_x = son.center.x - distance;
			ROI_center_y = son.center.y;
		}
		else if (delta_x < 0 && delta_y == 0)
		{
			ROI_center_x = son.center.x + distance;
			ROI_center_y = son.center.y;
		}
	}

	RotatedRect energy_ROI(Point2f(ROI_center_x, ROI_center_y), Size2f(distance * 2, distance * 2), 0);

	//确定ROI区域
    Rect energy_roi_rect = energy_ROI.boundingRect();

#ifdef SHOW_ROI
	if (energy_roi_rect.tl().x > 0 && energy_roi_rect.tl().y > 0 && energy_roi_rect.br().x < image.cols && energy_roi_rect.br().y < image.rows)
	{
		imshow("ROI", image(Rect(energy_roi_rect)));
	}
#endif // SHOW_ROI

	//获取ROI区域中待识别的R形logo
	for (int i = 0; i < rect.size(); i++)
	{
		if (rect[i].center.y < energy_roi_rect.br().y && rect[i].center.x > energy_roi_rect.tl().x &&
			rect[i].center.y > energy_roi_rect.tl().y && rect[i].center.x < energy_roi_rect.br().x)
		{
			float aspect_ratio;//限定R形logo的长宽比

			aspect_ratio = (rect[i].size.height > rect[i].size.width) ? rect[i].size.height / rect[i].size.width :
					rect[i].size.width / rect[i].size.height;
			if (aspect_ratio < 1.4)
			{
#ifdef MLR
				target_r.push_back(rect[i]);
#else
				if (son.size.area() / rect[i].size.area() > 1 && son.size.area() / rect[i].size.area() < 3)
				{
					target_r.push_back(rect[i]);
					break;
				}
#endif // MLR
			}
		}
	}
}

void buff_detect::machineLearning(Mat image, vector<RotatedRect> target_r, vector<RotatedRect>& final_r, Ptr<SVM> svm1)
{
	Rect roi;
	Mat target;
	Mat target_t;
	int response = 0;
	for (int i = 0; i < target_r.size(); i++)
	{
		roi = target_r[i].boundingRect();

		//��Ե����
		if (roi.tl().x < 0 || roi.tl().y < 0 || roi.br().x > image.cols || roi.br().y > image.rows)
		{
			continue;
		}

		target = image(Rect(roi));

		cvtColor(target, target_t, COLOR_BGR2GRAY);
		resize(target_t, target_t, Size(svmWidth, svmHeight));

		Mat p = target_t.reshape(1, 1);
		p.convertTo(p, CV_32FC1);
		response = (int)svm1->predict(p);

		if (response == 1)
		{
			final_r.push_back(target_r[i]);

			//char imagename[100];
			//sprintf_s(imagename, "%s%d.jpg", "./R/Pos/R_r_1", num);
			//resize(target_t, target_t, Size(48, 48));
			//imwrite(imagename, target_t);
			//num++;

			break;
		}
		//else
		//{
		//	char imagename[100];
		//	sprintf_s(imagename, "%s%d.jpg", "./R/Neg/f_45", num);
		//	resize(target_t, target_t, Size(48, 48));
		//	imwrite(imagename, target_t);
		//	num++;
		//}
	}
}
